package com.wteam.service.impl;

//import com.wteam.mapper.shopmapper;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wteam.PoJo.DTO.*;
import com.wteam.PoJo.VO.*;
import com.wteam.config.JWT.jwt;
import com.wteam.exception.SQLIntegrityConstraintViolation;
import com.wteam.mapper.*;
import com.wteam.service.MemberService;
import com.wteam.untils.MemberIdAndName;
import com.wteam.untils.Result;
import com.wteam.untils.aliyun.AliOSS;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class MemberServiceimpl implements MemberService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RegionMapper regionMapper;
    @Autowired
    private Couponmapper couponmapper;
    @Autowired
    private Membermapper membermapper;
    @Autowired
    private HttpServletRequest httpServletRequest;
    @Autowired
    private Memberdtomapper memberdtomapper;
    @Autowired
    private WalletMapper walletMapper;
    @Autowired
    private AliOSS aliOSS;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CouponMenmbermapper couponMenmbermapper;


    @Autowired
    private MemberIdAndName memberIdAndName;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(member member) throws Exception {
        LambdaQueryWrapper<member> qw = new LambdaQueryWrapper<member>();
        qw.eq(com.wteam.PoJo.VO.member::getUsername, member.getUsername());
        if (membermapper.selectOne(qw) != null) {
            throw new SQLIntegrityConstraintViolation("用户名已存在");
        }

        LambdaQueryWrapper<member> qw1 = new LambdaQueryWrapper<member>();
        qw1.eq(com.wteam.PoJo.VO.member::getMobile, member.getMobile());
        if (membermapper.selectOne(qw1) != null) {
            throw new SQLIntegrityConstraintViolation("手机号已被注册");
        }
        //密码进行MD5加密
        member.setPassword(DigestUtils.md5DigestAsHex(member.getPassword().getBytes(StandardCharsets.UTF_8)));
        member.setUpdateBy(member.getUsername());
        membermapper.insert(member);
    }


    @Override
    public Result list(login login) {
        LambdaQueryWrapper<member> lambdaQueryWrapper = new LambdaQueryWrapper();

        lambdaQueryWrapper.eq(member::getMobile, login.getMobile())
                .eq(member::getPassword, DigestUtils.md5DigestAsHex(login.getPassword()
                        .getBytes(StandardCharsets.UTF_8)));

        Long a = membermapper.selectCount(lambdaQueryWrapper);
        log.info("{}" + a);
        member member = membermapper.selectOne(lambdaQueryWrapper);
        if (a == 1) {
            Map<String, Object> claams = new HashMap<>();
            claams.put("username", member.getUsername());
            claams.put("id", member.getId());
            String s = jwt.generateJwt(claams);
            memberdto m = new memberdto();
            m.setLast_login_date(LocalDateTime.now());
            m.setId(member.getId());
            memberdtomapper.updateById(m);
            LoginMember loginMember = new LoginMember();
            //存token
            loginMember.setToken(s);
            LambdaQueryWrapper<memberdto> lambdaQueryWrapper1 = new LambdaQueryWrapper();

            lambdaQueryWrapper1.eq(memberdto::getMobile, login.getMobile())
                    .eq(memberdto::getPassword, DigestUtils.md5DigestAsHex(login.getPassword()
                            .getBytes(StandardCharsets.UTF_8)));
            memberdto memberdto = memberdtomapper.selectOne(lambdaQueryWrapper1);
            BeanUtils.copyProperties(memberdto, loginMember);
            return Result.success(loginMember);

        } else {
            return Result.error("密码错误");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String upload(MultipartFile file) throws IOException {
        log.info("DRFGDFGD{}", file);
        String url = aliOSS.upload(file);

        Map<String, Object> claims = jwt.parseJWT(httpServletRequest.getHeader("token"));
        String h = (String) claims.get("username");
       Integer memberid= (Integer) claims.get("id");
        System.out.println("请求头姓名" + h);
        membermapper.upload(url, h);
        //删除缓存
        String key = "mydetial" + "::" + memberid;
        redisTemplate.delete(key);
        return url;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result savewallet(@Validated walletPassword walletPassword) {
        Map<String, Object> claims = jwt.parseJWT(httpServletRequest.getHeader("token"));
        String h = (String) claims.get("username");
        Integer MemberId = (Integer) claims.get("id");
        log.info(h + MemberId);
        //判断是不是有密码了
        LambdaQueryWrapper<member_wallet> qw = new LambdaQueryWrapper();
        qw.eq(member_wallet::getMemberId, MemberId)
                .eq(member_wallet::getMemberName, h);
        Long aLong = walletMapper.selectCount(qw);
        log.info(aLong.toString() + "sdiojfsdnfmskjdnc");
        if (aLong != 0) {
            return Result.error("该账号已设置密码");
        }


        if (!walletPassword.getPassword().equals(walletPassword.getReceicve())) {
            return Result.error("确认密码错误，请检查");
        }
        member_wallet memberWallet = new member_wallet();
        //密码进行MD5加密
        memberWallet.setWalletPassword(DigestUtils.md5DigestAsHex(walletPassword.getPassword().getBytes(StandardCharsets.UTF_8)));

        memberWallet.setMemberId(MemberId);
        memberWallet.setMemberName(h);
        int insert = walletMapper.insert(memberWallet);
        return insert == 1 ? Result.success("密码设置成功") : Result.error("密码设置失败，请联系管理员");


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result savemoney(money money) {
        Map<String, Object> claims = jwt.parseJWT(httpServletRequest.getHeader("token"));
        String h = (String) claims.get("username");
        Integer MemberId = (Integer) claims.get("id");

        LambdaQueryWrapper<member_wallet> qw = new LambdaQueryWrapper();

        qw.eq(member_wallet::getMemberId, MemberId)
                .eq(member_wallet::getMemberName, h);

        member_wallet memberWallet = new member_wallet();

        Long aLong = walletMapper.selectCount(qw);
        if (aLong == 0) {
            return Result.error("请先完善账户密码");
        }
        memberWallet.setMemberWallet(money.getMoney());
        int update = walletMapper.update(memberWallet, qw);
        return Result.success("成功充值了" + money.getMoney());
    }


    @Override
    public Result selectMyCopon() {
        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));
        LambdaQueryWrapper<coupon_member> qw = new LambdaQueryWrapper<>();
        qw.eq(coupon_member::getMemberId, memberid);
        //遍历优惠卷，添加我的优惠卷
        List<coupon> coupons = new ArrayList<>();
        //遍历优惠卷，
        List<coupon_member> coupon_members = couponMenmbermapper.selectList(qw);
        log.info(coupon_members.toString());
        if (coupon_members.size() == 0 || coupon_members.equals(null)) {

            return Result.success("你还没有优惠卷");
        }

        for (coupon_member member : coupon_members) {

            Integer couponId = member.getCouponId();
            coupon coupon = couponmapper.selectById(couponId);
            coupon.setState(member.getState());
            coupons.add(coupon);
        }
//分类使用和未使用
        String key = memberid + "_my_coupon";
        redisTemplate.opsForValue().set(key, Result.success(coupons));
        return Result.success(coupons);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result AddAddress(regionvo regionvo) {
        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));
        region region = new region();
        region.setMemberId(memberid);
        BeanUtils.copyProperties(regionvo, region);
        //1.先判断用户有没有默认地址,没有强制设为默认
        LambdaQueryWrapper<region> qw = new LambdaQueryWrapper<>();
        qw.eq(com.wteam.PoJo.DTO.region::getMemberId, memberid)
                .eq(com.wteam.PoJo.DTO.region::getDefaultAddress, 2);
        com.wteam.PoJo.DTO.region region1 = regionMapper.selectOne(qw);
        //这里为没有默认，需强行改变
        if (region1 == null) {

            region.setDefaultAddress(2);
            regionMapper.insert(region);
        }
        //说明已有默认地址
        //判断是不是要设默认1为不要,直接插入
        else if (region.getDefaultAddress() == 1) {
            regionMapper.insert(region);
        } else if (region.getDefaultAddress() == 2) {
            //改原有默认地址为1
            LambdaQueryWrapper<region> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(com.wteam.PoJo.DTO.region::getDefaultAddress, 2)
                    .eq(com.wteam.PoJo.DTO.region::getMemberId, memberid);
            region updataaddress = new region();
            updataaddress.setMemberId(memberid);
            updataaddress.setDefaultAddress(1);
            regionMapper.update(updataaddress, lambdaQueryWrapper);
            regionMapper.insert(region);
        } else {
            return Result.error("系统异常，请联系管理员");
        }
//        //更新原有的member中表格的默认地址

        com.wteam.PoJo.DTO.region region2 = regionMapper.selectOne(qw);
        memberdto memberdto = new memberdto();
        memberdto.setId(region2.getMemberId());
        memberdto.setRegionId(region2.getId());
        memberdto.setRegion(region2.getProvince() + region2.getUrban() + region2.getFullAddress());
        memberdtomapper.updateById(memberdto);

        return Result.success("地址信息添加成功");
    }

    @Override
    public Result listAddress() {
        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));
        LambdaQueryWrapper<region> qw = new LambdaQueryWrapper();
        qw.eq(region::getMemberId, memberid);
        List<region> regions = regionMapper.selectList(qw);
        return Result.success(regions);
    }

    @Override
    public Result updateAddress(Integer regionId) {
        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));
        //将原有的改为默认为1
        LambdaQueryWrapper<region> qw = new LambdaQueryWrapper<>();
        qw.eq(region::getMemberId, memberid)
                .eq(region::getDefaultAddress, 2);
        region region1 = new region();
        region1.setDefaultAddress(1);
        regionMapper.update(region1, qw);
        //将reginId改为2
        LambdaQueryWrapper<region> qw1 = new LambdaQueryWrapper<>();
        qw1.eq(region::getMemberId, memberid)
                .eq(region::getId, regionId);
        region region2 = new region();
        region1.setDefaultAddress(2);
        regionMapper.update(region1, qw1);
        //将member的地址也改
        region region3 = regionMapper.selectOne(qw);
        memberdto memberdto = new memberdto();
        memberdto.setId(region3.getMemberId());
        memberdto.setRegionId(region3.getId());
        memberdto.setRegion(region3.getProvince() + region3.getUrban() + region3.getFullAddress());
        memberdtomapper.updateById(memberdto);
        return Result.success("收货默认地址修改成功");
    }

    @Override
    public Result SharePoint(Integer point) {
        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));
        memberdto memberdto = memberdtomapper.selectById(memberid);
        memberdto.setPoint(memberdto.getPoint() + point);
        memberdtomapper.updateById(memberdto);
        //删除我个人缓存
        String key = "mydetial" + "::" + memberid;
        redisTemplate.delete(key);
        return Result.success("分享成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result signpoint() {
        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));
        LocalDateTime now = LocalDateTime.now();
        String key = "sign:" + memberid + now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
        int dayofMonth = now.getDayOfMonth();
        //先判断今天是不是已经签到了
        Boolean bit = stringRedisTemplate.opsForValue().getBit(key, dayofMonth - 1);
        if (bit) {
            return Result.error("今天已经签到");
        }
        //加积分
        LambdaQueryWrapper<memberdto> qw = new LambdaQueryWrapper();
        qw.eq(memberdto::getId, memberid);
        memberdto memberdto = memberdtomapper.selectById(memberid);
        memberdto.setPoint(memberdto.getPoint() + 1000);
        stringRedisTemplate.opsForValue().setBit(key, dayofMonth - 1, true);
        int update = memberdtomapper.update(memberdto, qw);
        //删除我个人信息缓存
        String memerkey = "mydetial" + "::" + memberid;
        redisTemplate.delete(memerkey);
        return Result.success("签到成功");
    }

    @Override
    public Result selectsign() {
        List<sign> sign = new ArrayList<>();
        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));
        //拼接key
        LocalDateTime now = LocalDateTime.now();
        String key = "sign:" + memberid + now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
//获取本月的全部签到记录
        List<Long> list = stringRedisTemplate.opsForValue().bitField(
                key, BitFieldSubCommands.create()
                        .get(BitFieldSubCommands
                                .BitFieldType.unsigned(now.getDayOfMonth()))
                        .valueAt(0));
        if (list == null || list.isEmpty()) {

            return Result.success(sign);
        }
        Long num = list.get(0);
        if (num == 0 || num == null) {
            return Result.success(sign);
        }
//遍历集合做位于运算
//        Map<String, Object> sign = new LinkedHashMap<>();
        List<sign> signs = new ArrayList<>();
        for (int i = now.getDayOfMonth(); i > 0; i--) {
            if ((num & 1) == 1) {
                sign s = new sign();

                String data = now.format(DateTimeFormatter.ofPattern("yyyyMM")) + "" + i;
                s.setDate(data);
                s.setSignInFlag(true);

                signs.add(s);
            }
//            } else {
//                String data = now.format(DateTimeFormatter.ofPattern("yyyyMM")) + "" + i;
//                sign s = new sign();
//                s.setDate(data);
//                s.setSignInFlag(false);
//                signs.add(s);
////                sign.put(data, false);
//            }
            num >>>= 1;
        }

        return Result.success(signs);
    }

    @Override
    public Result<memberpoint> selectMypoint() {

        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));

        memberdto memberdto = memberdtomapper.selectById(memberid);
        memberpoint memberpoint = new memberpoint();
        memberpoint.setPoint(memberdto.getPoint());
        return Result.success(memberpoint);
    }

    @Override
    public Result<memberdto> selectMybody() {
        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));
        String key = "mydetial" + "::" + memberid;
        //看我是不是有缓存
        memberdto memberdto = (com.wteam.PoJo.DTO.memberdto) redisTemplate.opsForValue().get(key);


        if (memberdto == null) {
            //没缓存
            memberdto member = memberdtomapper.selectById(memberid);
            //添加我的信息的缓存
            redisTemplate.opsForValue().set(key, member);
            return Result.success(member);
        }
        //有缓存
        return Result.success(memberdto);
    }

    @Override
    public Result fixmybody(fixmybody fixmybody) {
        Integer memberid = memberIdAndName.Memberid(httpServletRequest.getHeader("token"));
        memberdto memberdto = new memberdto();
        BeanUtils.copyProperties(fixmybody, memberdto);
        memberdto.setId(memberid);
        memberdtomapper.updateById(memberdto);
        memberdto memberdto1 = memberdtomapper.selectById(memberid);
        //删除缓存
        String key = "mydetial" + "::" + memberid;
        redisTemplate.delete(key);
        return Result.success(memberdto1);
    }
}

